#include "CenarioJogo.h"
#include "TPinterface.h"

#define BUFSIZE 256
GLuint selectBuf[BUFSIZE];

TPinterface::TPinterface()
{
	fcx = -1;
	fcy = -1;
}

void TPinterface::processKeyboard(unsigned char key, int x, int y)
{
	CGFinterface::processKeyboard(key, x, y);
	switch(key)
	{
		case 'l':
		{
			((CenarioJogo *) scene)->toggleLight();
			break;
		}
		case 'L':
		{
			((CenarioJogo *) scene)->toggleLight();
			break;
		}
		case 'u':
		{
			if(!((CenarioJogo *) scene)->isGameOver())
				((CenarioJogo *) scene)->processUndo();
			break;
		}
		case 'U':
		{
			if(!((CenarioJogo *) scene)->isGameOver())
				((CenarioJogo *) scene)->processUndo();
			break;
		}
		case 't':
		{
			((CenarioJogo *) scene)->changeTexture();
			break;
		}
		case 'T':
		{
			((CenarioJogo *) scene)->changeTexture();
			break;
		}
		case 'j':
		{
			((CenarioJogo *) scene)->printPlayList();
			break;
		}
		case 'J':
		{
			((CenarioJogo *) scene)->printPlayList();
			break;
		}
		case 'x':
		{
			if(!((CenarioJogo *) scene)->isGameOver())
			{
				fcx = -1;
				fcy = -1;
				((CenarioJogo *) scene)->deselect();
				((CenarioJogo *) scene)->setMessage("Jogada cancelada.");
			}
			break;
		}
		case 'X':
		{
			if(!((CenarioJogo *) scene)->isGameOver())
			{
				fcx = -1;
				fcy = -1;
				((CenarioJogo *) scene)->deselect();
				((CenarioJogo *) scene)->setMessage("Jogada cancelada.");
			}
			break;
		}
		case 'r':
		{
			((CenarioJogo *) scene)->restartGame();
			((CenarioJogo *) scene)->setMessage("Jogo reiniciado.");
			printf("Jogo reiniciado.\n");
			break;
		}
		case 'R':
		{
			((CenarioJogo *) scene)->restartGame();
			((CenarioJogo *) scene)->setMessage("Jogo reiniciado.");
			printf("Jogo reiniciado.\n");
			break;
		}
		case 'q':
		{
			((CenarioJogo *) scene)->closeCom();
			exit(0);
			break;
		}
		case 'Q':
		{
			((CenarioJogo *) scene)->closeCom();
			exit(0);
			break;
		}
	};
}

void TPinterface::initGUI()
{
	
}

void TPinterface::processGUI(GLUI_Control *ctrl)
{
	
}

void TPinterface::processMouse(int button, int state, int x, int y) 
{
	CGFinterface::processMouse(button,state, x, y);
	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
		performPicking(x,y,false);
	else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
		performPicking(x,y,true);
}

void TPinterface::performPicking(int x, int y, bool tumb) 
{
	glSelectBuffer (BUFSIZE, selectBuf);
	glRenderMode(GL_SELECT);
	glInitNames();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix ();
	GLfloat projmat[16];
	glGetFloatv(GL_PROJECTION_MATRIX,projmat);
	glLoadIdentity();
	GLint viewport[4];
	glGetIntegerv(GL_VIEWPORT, viewport);
	gluPickMatrix ((GLdouble) x, (GLdouble) (CGFapplication::height - y), 5.0, 5.0, viewport);
	glMultMatrixf(projmat);
	scene->display();
	glMatrixMode (GL_PROJECTION);
	glPopMatrix ();
	glFlush();
	GLint hits;
	hits = glRenderMode(GL_RENDER);
	processHits(hits, selectBuf,tumb);
}

void TPinterface::processHits (GLint hits, GLuint buffer[], bool tumb) 
{
	GLuint *ptr = buffer;
	GLuint mindepth = 0xFFFFFFFF;
	GLuint *selected = NULL;
	GLuint nselected;
	for (int i = 0; i < hits; i++)
	{
		int num = *ptr; ptr++;
		GLuint z1 = *ptr; ptr++;
		ptr++;
		if (z1 < mindepth && num > 0)
		{
			mindepth = z1;
			selected = ptr;
			nselected = num;
		}
		for (int j = 0; j < num; j++) 
			ptr++;
	}
	if (selected != NULL)
	{
		if((selected[0] >= 0 || selected[1] >= 0) && !(selected[0] == fcx && selected[1] == fcy) && !((CenarioJogo *) scene)->isAnimating() && ((CenarioJogo *) scene)->getPlayer(((CenarioJogo *) scene)->getTurn())->getHumano() && !((CenarioJogo *) scene)->isGameOver())
		{
			if(fcx < 0 || fcy < 0)
			{
				if(((CenarioJogo *) scene)->isCasaNotEmpty(selected[0],selected[1]))
				{
					if(((CenarioJogo *) scene)->isCasaOwner(selected[0],selected[1]))
					{
						((CenarioJogo *) scene)->clearMessage();
						fcx = selected[0];
						fcy = selected[1];
						tumbling = tumb;
						((CenarioJogo *) scene)->select(fcx,fcy);
					}
					else
					{
						((CenarioJogo *) scene)->setMessage("Nao e o dono desse monte.");
					}
				}
			}
			else
			{
				bool valid = ((CenarioJogo *) scene)->processMovement(fcx,fcy,selected[0],selected[1],tumbling);
				if(valid)
				{
					((CenarioJogo *) scene)->clearMessage();
					((CenarioJogo *) scene)->deselect();
					fcx = -1;
					fcy = -1;
				}
				else
				{
					((CenarioJogo *) scene)->setMessage("Jogada invalida.");
				}
			}
		}
	}	
}